﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace EventSym
{
    public class EventController  {
        private Dictionary<string ,Delegate> m_eventDic = new Dictionary<string, Delegate>();
//        private List<string> m_permanentList = new List<string>();

        private void OnListenerAdding(string eventname, Delegate del)
        {
            if (!m_eventDic.ContainsKey(eventname))
            {
                m_eventDic.Add(eventname,null);
            }
            Delegate @delegate = m_eventDic[eventname];
            if (@delegate != null && @delegate.GetType() != del.GetType())
            {
                throw new  EventException(
                    "不能添加委托，因为类型不匹配 需要的类型：" + @delegate.GetType() + "当前的类型" + del.GetType());
            }
        }

        private bool OnListenerRemoveing(string eventname,Delegate del)
        {
            if (!m_eventDic.ContainsKey(eventname))
            {
                return false;
            }
            Delegate @delegate = m_eventDic[eventname];
            if (@delegate != null && @delegate.GetType() != del.GetType())
            {
                throw new EventException(
                    "不能添加委托，因为类型不匹配 需要的类型：" + @delegate.GetType() + "当前的类型" + del.GetType());
            }
            return true;
        }

        private void OnListenerRemoved(string eventname)
        {
            if (m_eventDic.ContainsKey(eventname))
            {
                if (m_eventDic[eventname] == null)
                {
                    m_eventDic.Remove(eventname);
                }
            }
        }

        public void AddEventListener(string eventname,Action del)
        {
            OnListenerAdding(eventname,del);
            m_eventDic[eventname] = (Action) Delegate.Combine((Action) m_eventDic[eventname], del);
        }
        public void AddEventListener<T>(string eventname,Action<T> del)
        {
            OnListenerAdding(eventname,del);
            m_eventDic[eventname] = (Action<T>) Delegate.Combine((Action<T>) m_eventDic[eventname], del);
        }
        public void AddEventListener<T,U>(string eventname,Action<T,U> del)
        {
            OnListenerAdding(eventname,del);
            m_eventDic[eventname] = (Action<T,U>) Delegate.Combine((Action<T,U>) m_eventDic[eventname], del);
        }
        public void AddEventListener<T,U,S>(string eventname,Action<T,U,S> del)
        {
            OnListenerAdding(eventname,del);
            m_eventDic[eventname] = (Action<T,U,S>) Delegate.Combine((Action<T,U,S>) m_eventDic[eventname], del);
        }
        public void AddEventListener<T,U,S,K>(string eventname,Action<T,U,S,K> del)
        {
            OnListenerAdding(eventname,del);
            m_eventDic[eventname] = (Action<T,U,S,K>) Delegate.Combine((Action<T,U,S,K>) m_eventDic[eventname], del);
        }
//        public void AddEventListener<T,U,S,K,KI>(string eventname,Action<T,U,S,K,KI> del)
//        {
//            OnListenerAdding(eventname,del);
//            m_eventDic[eventname] = (Action<T,U,S,K,KI>) Delegate.Combine((Action<T,U,S,K,KI>) m_eventDic[eventname], del);
//        }

        public void RemEventListener(string eventname, Action del)
        {
            if (OnListenerRemoveing(eventname, del))
            {
                m_eventDic[eventname] = (Action)Delegate.Remove((Action)m_eventDic[eventname],del);
                OnListenerRemoved(eventname);
            }
        }
        public void RemEventListener<T>(string eventname, Action<T> del)
        {
            if (OnListenerRemoveing(eventname, del))
            {
                m_eventDic[eventname] =(Action<T>) Delegate.Remove((Action<T>)m_eventDic[eventname],del);
                OnListenerRemoved(eventname);
            }
        }
        public void RemEventListener<T,U>(string eventname, Action<T,U> del)
        {
            if (OnListenerRemoveing(eventname, del))
            {
                m_eventDic[eventname] =(Action<T,U>) Delegate.Remove((Action<T,U>)m_eventDic[eventname],del);
                OnListenerRemoved(eventname);
            }
        }
        public void RemEventListener<T,U,S>(string eventname, Action<T,U,S> del)
        {
            if (OnListenerRemoveing(eventname, del))
            {
                m_eventDic[eventname] =(Action<T,U,S>) Delegate.Remove((Action<T,U,S>)m_eventDic[eventname],del);
                OnListenerRemoved(eventname);
            }
        }
        public void RemEventListener<T,U,S,K>(string eventname, Action<T,U,S,K> del)
        {
            if (OnListenerRemoveing(eventname, del))
            {
                m_eventDic[eventname] =(Action<T,U,S,K>) Delegate.Remove((Action<T,U,S,K>)m_eventDic[eventname],del);
                OnListenerRemoved(eventname);
            }
        }
//        public void RemEventListener<T,U,S,K,I>(string eventname, Action<T,U,S,K,I> del)
//        {
//            if (OnListenerRemoveing(eventname, del))
//            {
//                m_eventDic[eventname] =(Action<T,U,S,K,I>) Delegate.Remove((Action<T,U,S,K,I>)m_eventDic[eventname],del);
//                OnListenerRemoved(eventname);
//            }
//        }

        public void ClearEventListener()
        {
            m_eventDic.Clear();
        }

        public bool IsHaveEventListener(string eventname)
        {
            return m_eventDic.ContainsKey(eventname);
        }

        public void BroadCastEvent(string eventname)
        {
            if (IsHaveEventListener(eventname))
            {
                Action del = m_eventDic[eventname] as Action;
                if (del != null)
                {
                    del.Invoke();
                }
            }
        }
        public void BroadCastEvent<T>(string eventname,T t)
        {
            if (IsHaveEventListener(eventname))
            {
                Action<T> del = m_eventDic[eventname] as Action<T>;
                if (del != null)
                {
                    del.Invoke(t);
                }
            }
        }
        public void BroadCastEvent<T,U>(string eventname,T t,U u)
        {
            if (IsHaveEventListener(eventname))
            {
                Action<T,U> del = m_eventDic[eventname] as Action<T,U>;
                if (del != null)
                {
                    del.Invoke(t,u);
                }
            }
        }
        public void BroadCastEvent<T,U,S>(string eventname,T t,U u,S s)
        {
            if (IsHaveEventListener(eventname))
            {
                Action<T,U,S> del = m_eventDic[eventname] as Action<T,U,S>;
                if (del != null)
                {
                    del.Invoke(t,u,s);
                }
            }
        }
        public void BroadCastEvent<T,U,S,K>(string eventname,T t,U u,S s,K k)
        {
            if (IsHaveEventListener(eventname))
            {
                Action<T,U,S,K> del = m_eventDic[eventname] as Action<T,U,S,K>;
                if (del != null)
                {
                    del.Invoke(t,u,s,k);
                }
            }
        }
//        public void BroadCastEvent<T,U,S,K,I>(string eventname,T t,U u,S s,K k,I i)
//        {
//            if (IsHaveEventListener(eventname))
//            {
//                Action<T,U,S,K,I> del = m_eventDic[eventname] as Action<T,U,S,K,I>;
//                if (del != null)
//                {
//                    del.Invoke(t,u,s,k,i);
//                }
//            }
//        }

        public Dictionary<string, Delegate> EventDic
        {
            get { return m_eventDic; }
        }
    }
}

